﻿namespace PokerSimulator
{
	using System;
	using System.Collections.ObjectModel;
	using System.Globalization;

	using PugLib.Extensions.Collections;

	public class Log
	{
		private const string PercentageStringFormat = "{0:00.000%}";

		private readonly GameTally _losingHands;
		private readonly GameTally _winningHands;
		private int _allWinners;
		private int _splitPots;
		private bool _verbose;

		public Log()
		{
			_winningHands = new GameTally();
			_losingHands = new GameTally();
		}

		public bool Verbose
		{
			get { return _verbose; }
			set { _verbose = value; }
		}

		public void AddHands(HandCollection hands)
		{
			hands.Sort();
			int c = hands.Count - 1;
			double winningValue = hands[c].Value;
			int splitPotCount = 0;
			double currentValue;
			// handle split pots
			for (int i = c; i >= 0; i--)
			{
				currentValue = hands[i].Value;
				if (currentValue != winningValue)
				{
					break;
				}
				_winningHands.Add(currentValue);
				splitPotCount++;
			}

			// tally split pots
			if (splitPotCount > 1)
			{
				_splitPots++;
			}
			if (splitPotCount == c)
			{
				_allWinners++;
			}
			else
			{
				for (int j = splitPotCount; j < c; j++)
				{
					currentValue = hands[j].Value;
					if (currentValue > 0)
					{
						_losingHands.Add(currentValue);
					}
				}
			}
		}

		public static void WinningHand(Hand hand)
		{
			Console.WriteLine(string.Format(NumberFormatInfo.InvariantInfo, "{0:0.00000000}: {1}", hand.Value, hand.Description));
		}

		public static void PrintPercentages(GameTally tally)
		{
			double total = Convert.ToDouble(tally.GetTotal());
			if (total == 0)
			{
				total = 1;
			}
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " Straight Flush", tally.GetStraightFlushCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " Four of a Kind", tally.Get4KindCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " Full House", tally.GetFullHouseCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " Flush", tally.GetFlushCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " Straight", tally.GetStraightCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " Three of a Kind", tally.Get3KindCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " Two Pair", tally.Get2PairCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " High Card", tally.GetHighCardCount() / total));
			Console.WriteLine(string.Format(CultureInfo.InvariantCulture, PercentageStringFormat + " All Folded", tally.GetAllFoldedCount() / total));
		}


		public static void Report(Log log)
		{
			// split pots
			PrintDividerLine();
			Console.WriteLine("Number of split pots: " + log._splitPots);
			Console.WriteLine("Number of pots with all winners: " + log._allWinners);
			PrintDividerLine();
			Console.WriteLine("Winning Hand Percentages:");
			PrintPercentages(log._winningHands);
			PrintDividerLine();
			Console.WriteLine("Losing Hand Percentages:");
			PrintPercentages(log._losingHands);
			PrintDividerLine();
		}

		private static void PrintDividerLine()
		{
			Console.WriteLine("===================================");
		}

		public void AddLog(Log inputLog)
		{
			_allWinners += inputLog._allWinners;
			_splitPots += inputLog._splitPots;

			inputLog._winningHands.WinningValues.ForEach(value => _winningHands.Add(value));
			inputLog._losingHands.WinningValues.ForEach(value => _losingHands.Add(value));
		}

		public static void PrintSummary(Game game)
		{
			PrintStarLine();
			Console.WriteLine("Shared Cards:" + game.SharedHand);
			ReadOnlyCollection<string> handsOutput = game.Hands.Display();
			handsOutput.ForEach(Console.WriteLine);
			PrintStarLine();
		}

		public static void ReportGame(Game game)
		{
			PrintReportHeader(game);
			Report(game.Log);
		}

		public static void PrintReportHeader(Game game)
		{
			PrintStarLine();
			Console.WriteLine("Game: Texas Hold Em");
			Console.WriteLine("Players: " + game.PlayerCount);
			Console.WriteLine("Rounds: " + game.GamesToPlay);
			PrintStarLine();
		}

		protected static void PrintStarLine()
		{
			Console.WriteLine("***************************************************");
		}

		public static void ReportProgress(int round, long statusCount, long totalCount)
		{
			if (statusCount == 0)
			{
				return;
			}
			if (0 == (round % statusCount))
			{
				Console.WriteLine(string.Format(NumberFormatInfo.InvariantInfo, ">>>>> Approximately {0:0%} done", (float)round / totalCount));
			}
		}
	}

	public enum StatisticType
	{
		None = 0,
		Win = 1,
		Loss = 2
	}
}